package org.zxp.thread.ccontainer;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * @program: zxp-thread-test
 * @description: 同步容器用法，如果是非同步容器则容易出现一个线程遍历，一个线程修改最终报错
 * @author: X-Pacific zhang
 * @create: 2019-05-24 09:56
 **/
public class SyncContainer {


    /**
     * 单线程错误的迭代移出方式
     */
    @Test
    public void testError(){
        List arr = new ArrayList();
        for (int i = 0; i < 1024; i++) {
            arr.add(i);
        }
        arr.forEach(i -> arr.remove(i));//ConcurrentModificationException
    }

    /**
     * 单线程正确的迭代移出方式
     */
    @Test
    public void testRight(){
        List arr = new ArrayList();
        for (int i = 0; i < 1024; i++) {
            arr.add(i);
        }
        Iterator iterator = arr.iterator();
        while(iterator.hasNext()){
            iterator.next();
            iterator.remove();
        }
        System.out.println(arr.size());
    }

    /**
     * 多线程情况下iterator迭代移出的问题（多线程不可以同时操作一个迭代器）
     */
    @Test
    public void testIteratorRemove(){
        List<Integer> arr = new ArrayList();
        for (int i = 0; i < 1024; i++) {
            arr.add(i);
        }
        Iterator<Integer> iterator = arr.iterator();
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {//同时搞一个迭代器也是有问题的
//                synchronized (iterator){//加同步锁可以解决
                    while(iterator.hasNext()){
                        int num = iterator.next();
                        if(num == 4)
                            iterator.remove();
//                    }
                }
            }).start();
        }
    }


    /**
     * 同步容器测试
     */
    @Test
    public void testSContainer() {
        List<Integer> arr = new ArrayList();
        for (int i = 0; i < 1024; i++) {
            arr.add(i);
        }
        List<Integer> l = Collections.synchronizedList(arr);
//        synchronizedList的内部锁，那是在并发执行add/remove的时候，不要把多个线程的东西加到list内部实现的同一个位置上去，
//        并不能保证迭代原子性更无法解决并发迭代删除的问题
//        不好用
    }

    /**
     * copyonwrite
     * concurrent
     * blockingqueue
     */
}
